<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="shortcut icon" type="image/x-icon" href="../favicon.ico"/>
    <title>如何实现 layout 功能 jetbrick-template</title>

    <link href="../assets/css/application.min.css" rel="stylesheet" type="text/css"/>

    <!--[if lt IE 9]><script src="../assets/js/html5shiv.js"></script><![endif]-->
    <script type="text/javascript" src="../assets/js/application.min.js"></script>
</head>

<body>
<a href="https://github.com/subchen/jetbrick-template/" target="_blank">
    <img src="../assets/images/forkme_right_orange.png" alt="Fork me on GitHub" class="fork-me-on-github">
</a>

<div class="jb-topbar">
    <div class="container">
        <a href="http://subchen.github.io/"><img src="../assets/images/logo-mini.png"/></a>
        <!--
        <ul class="menubar">
            <li><a href="">commons</a></li>
            <li><a href="">webmvc</a></li>
            <li><a href="">template</a></li>
            <li><a href="">orm</a></li>
            <li><a href="">widget</a></li>
            <li><a href="">javadoc-chm</a></li>
        </ul>
        -->
        <div class="pull-right" style="color:#fff;line-height:40px;font-size:16px;padding-right:20px">QQ 交流圈：310491655</div>
    </div>
</div>

<div class="jb-banner">
    <div class="container">
        <a href="http://subchen.github.io/jetbrick-template/index.html">
            <img src="../assets/images/jetbrick-template-logo.png" class="pull-left" />
        </a>
        <ul class="description">
            <li>1. 全新一代 Java 模板引擎</li>
            <li>2. 具有高性能、高扩展性</li>
            <li>3. 完美替代 JSP, Velocity 等引擎模板</li>
        </ul>
        <a href="download/jetbrick-template-1.2.3.zip" class="download-button">
            <img src="../assets/images/download.png"/>
            <span>jetbrick-template-1.2.3.zip<br/>2014-03-10</span>
        </a>
    </div>
</div>

<div class="container">
    <div class="jb-section">
        <ul class="tabs">
            <li><a href="overview.html">简介</a></li>
            <li><a href="download.html">下载</a></li>
            <li><a href="userguide.html">开发指南</a></li>
            <li><a href="config.html">配置指南</a></li>
            <li><a href="syntax.html">语法指南</a></li>
            <li><a href="integrate.html">Web 框架集成</a></li>
            <!--
            <li><a href="example.html">例子</a></li>
            -->
            <li><a href="faq.html" class="selected">FAQ</a></li>
            <li><a href="about.html">关于</a></li>
        </ul>
    </div>
</div>

<div class="container">
    <div class="announcement">
        <a href="download.html#version">2014-03-10：jetbrick-template-1.2.3 正式版已发布，欢迎下载。</a>
    </div>
</div>

<div class="container">


    <div class="markdown">

<!-- markdown body begin -->
	<ul> 
 <li><a href="faq-compile.html">jetbrick-template 将模板编译成 Java Class 有什么好处？</a></li> 
 <li><a href="faq-define.html">jetbrick-template 中为什么需要 #define 声明变量类型？</a></li> 
 <li><a href="faq-error.html">jetbrick-template 常见错误分析</a></li> 
 <li><a href="faq-autoscan.html">jetbrick-template 如何让自动扫描发现用户自定义的扩展方法/函数/标签 Class</a></li> 
 <li><a href="faq-include.html">jetbrick-template 中如何嵌入子模板？（父子间参数传递）</a></li> 
 <li><a href="faq-tag.html">jetbrick-template 中如何自定义 Tag？</a></li> 
 <li><a href="faq-layout.html">jetbrick-template 中如何实现 layout 功能？</a></li> 
 <li><a href="faq-spring.html">jetbrick-template 在 Spring 中的集成方法</a></li> 
</ul>

    <h1><a name="x1867624595"></a><span>1 在 jetbrick-template 中如何实现 layout 功能</span></h1>
<p>通常页面都有一个布局，大体上有页面头部，尾部，以及正文三部分。头部和尾部内容基本上固定，只有正文是变化的。</p>
<p>jetbrick-template 可以使用 3 种方法实现模板的 layout 功能。</p> 
<ol> 
 <li><code>#include(file, ...)</code> 指令</li> 
 <li><code>#tag layout(file, ...)</code> 标签</li> 
 <li><code>#tag block(name)</code> + <code>#inlcude(file, ...)</code> 组合</li> 
</ol>
<h2><a name="x753318042"></a><span>1.1 常规模式</span></h2>
<p>我们将页面公共部分放在 include 文件中，然后在每个页面中应用 include 文件来实现内容共享。</p>
<p>main.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
#include("/include/header.jetx")
<table>  
  这是正文内容  
</table>  
#include("/include/footer.jetx")
]]></script>
<p>这个不算 layout?<br />呵呵，继续放下看。</p>
<h2><a name="x670265539"></a><span>1.2 变种模式</span></h2>
<p>常规模式中，只是共享了一些公共内容，但是并没有实现真正的 layout，因为 layout 一变，include 的方式可能就会发生变化，这样所有文件都要重新 include，不是很方便。</p>
<p>下面就是 #include 模式的变种（动态 include），来实现真正的 layout。</p>
<p>layout.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
<html>
  <head>
    <title>${title}</title>
  </head>
  <body>
    <div class="header">This is a logo image.</div>

    #include(parameter.pageUrl)

    <div class="footer">Copyright @2000-2010, All Rights Reserved.</div>
  </body>
</html>
]]></script>
<p>main.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
<table>  
  这是正文内容  
</table>
]]></script>
<p>Action.java</p> 
<script type="syntaxhighlighter" class="brush: java"><![CDATA[
String url = "/layout.jetx?pageUrl=" + URLEncoder.encode("/main.jetx", "utf-8);
RequestDispatcher rd = getServletContext().getRequestDispatcher(url);
rd.forward(request, response);
]]></script>
<p>怎么样？通过一个 pageUrl 参数来达到动态 layout 的目的，这样我们以后只要修改layout.jetx 文件就能达到修改所有页面布局了。</p>
<p>URL 访问方法： <a href="http://127.0.0.1:8080/layout.jetx?pageUrl=main.jetx">http://127.0.0.1:8080/layout.jetx?pageUrl=main.jetx</a></p>
<h2><a name="x38438688"></a><span>1.3 #tag layout(file, ...)</span></h2>
<p>这里再介绍一种采用 layout 自定义标签来实现。</p>
<p>layout.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
<html>
  <head>
    <title>${title}</title>
  </head>
  <body>
    <div class="header">This is a logo image.</div>

    ${bodyContent}

    <div class="footer">Copyright @2000-2010, All Rights Reserved.</div>
  </body>
</html>
]]></script>
<p>main.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
#tag layout("layout.jetx") 
<table>  
  这是正文内容  
</table>
#end
]]></script>
<p>layout 标签允许指定一个 layout 模板文件，在渲染页面的时候，会将layout标签体的渲染内容作为一个 bodyContent 变量插入到 layout 指定模板文件里。</p>
<p>这样，我们就可以通过直接访问 <a href="http://127.0.0.1:8080/main.jetx">http://127.0.0.1:8080/main.jetx</a></p>
<h2><a name="x902247563"></a><span>1.4 组合 #tag block() + #inlcude</span></h2>
<p>上面的 #tag layout() 标签只能嵌入一块自定义的内容 <code>${bodyContent}</code>，那么如果想要嵌入多个自定义的变量块呢？</p>
<p>main.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
#tag block("bodyContent1")
    BODY 1111
#end
#tag block("bodyContent2")
    BODY 2222
#end
#include ("layout.jetx")
]]></script>
<p>layout.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
This is a header.
<div>
    ${bodyContent1}
</div>
<div>
    ${bodyContent2}
</div>
This is a footer.
]]></script>
<p>输出结果：</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
This is a header.
<div>
    BODY 1111
</div>
<div>
    BODY 2222
</div>
This is a footer.
]]></script>
<p>怎么样？现在就可以随意的进行组合了。</p>
<h2><a name="x749955107"></a><span>1.5 block 的默认值和重载</span></h2>
<p>在 layout.jetx 中，我们也可以定义默认内容，在 main.jetx 中对默认内容进行重载，如下：</p>
<p>layout.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
This is a header.
<div>
#tag default_block("bodyContent1")
    This is a default BODY 1111
#end
</div>
<div>
#tag default_block("bodyContent2")
    This is a default BODY 2222
#end
</div>
This is a footer.
]]></script>
<p>main.jetx</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
#tag block("bodyContent1")
    Override block 111
#end
#include ("layout.jetx")
]]></script>
<p>输出结果：</p> 
<script type="syntaxhighlighter" class="brush: html"><![CDATA[
This is a header.
<div>
    Override block 111
</div>
<div>
    This is a default BODY 2222
</div>
This is a footer.
]]></script>
<h2><a name="x796152"></a><span>1.6 总结</span></h2>
<p>不管采用哪种方式，jetbrick-template 都提供很大的灵活性来实现页面布局功能。</p>
<p>其中自定义 #tag 标签机制提供了非常强大功能，很容易实现其他模板引擎难以实现的功能，比如像 JSP Taglib 一样实现自定义标签，如 Cache Tag 将内容缓存到 memecached/redis 的标签等等。</p>

<!-- markdown body end -->

    </div>
</div>

<div class="container">
    <div class="jb-footer">
        Copyright 2010-2014 Guoqiang Chen. All rights reserved.
        <br/>subchen&#64;gmail.com, QQ 交流圈：310491655
    </div>
</div>

<style type="text/css">
#cnzz_stat_icon_1000210720 {
	display: none;
}
</style>
<script type="text/javascript">
var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");
document.write(unescape("%3Cspan id='cnzz_stat_icon_1000210720'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s22.cnzz.com/z_stat.php%3Fid%3D1000210720' type='text/javascript'%3E%3C/script%3E"));
</script>



</body>
</html>
